package ru.niir.goodfil.db.handlers;

import ru.niir.goodfil.utils.validation.*;
import ru.niir.goodfil.db.GoodType;
import ru.niir.goodfil.db.Good;
import ru.niir.goodfil.exceptions.InvalidIdException;
import ru.niir.goodfil.exceptions.WrongHandlerException;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isBlank;

import java.util.List;

/**
 * Обработчик групп товаров
 * @see ru.niir.goodfil.db.GoodType группы товаров
 */
public class GoodTypeHandler extends Handler
{
    /**
     * Конструктор 
     */
    public GoodTypeHandler(Goodfil gf)
    {
        super(GoodType.class, gf);
    }

    /**
     * Проверки для группы товаров
     * 1. Идентификатор != 0, != 1
     * 2. parentId указан верно (FK)
     * 3. name заполнено
     * 4. name уникально в рамках родительской группы (IDX)
     * @param o группа товаров
     * @return результат проверки
     */
    public ValidationResult validate(Object o)
    {
        assert o != null;
        if (!(o instanceof GoodType)) throw new WrongHandlerException(klass, o.getClass());

        GoodType goodType = (GoodType) o;
        ValidationResult result = ValidationResult.Ok(GoodType.class);

        if (goodType.getId() == 0 || goodType.getId() == 1)
            result.addValidationError(new ValidationError("id", "id", goodType.getParentId(), ValidationProblem.REFERENCE, "Никакие операции нельзя выполнять с корневой группой"));

        if (!exists(GoodType.class, goodType.getParentId()))
            result.addValidationError(new ValidationError("parentId", "Родительская группа", goodType.getParentId(), ValidationProblem.REFERENCE));

        if (isBlank(goodType.getName()))
            result.addValidationError(new ValidationError("name", "Наименование", goodType.getName(), ValidationProblem.NOT_EMPTY));

        if (!checkGoodTypeNameUnique(goodType.getName(), goodType.getParentId(), goodType.getId()))
            result.addValidationError(new ValidationError("name", "Наименование", goodType.getName(), ValidationProblem.UNIQUE));

        return result;
    }

    /**
     * Проверить, возможно ли удалить группу товаров с заданным идентификатором.
     * Группу товаров можно удалить если:
     * 1. В ней отсутствуют товары
     * 2. В ней отсутствуют дочерние группы
     */
    public RemoveCheckResult removeCheck(long goodTypeId)
    {
        if (0 < (Long) getSession().createQuery("select count(*) from Good where goodTypeId = ?").setLong(0, goodTypeId).uniqueResult())
            return RemoveCheckResult.Error(GoodType.class, Good.class);

        if (0 < (Long) getSession().createQuery("select count(*) from GoodType where parentId = ?").setLong(0, goodTypeId).uniqueResult())
            return RemoveCheckResult.Error(GoodType.class, GoodType.class);

        return RemoveCheckResult.Ok(GoodType.class);
    }

    /**
     * Проверка на уникальность имени группы товаров внитри родительской группы.
     * @param goodTypeName имя группы товаров
     * @param parentGoodTypeId идентификатор родительской группы товаров
     * @param id идентификатор проверяемой группы товаров
     * @return true, если имя указанной группы товаров уникально внутри ее родительской группы товаров
     */
    private boolean checkGoodTypeNameUnique(String goodTypeName, long parentGoodTypeId, long id)
    {
        if (!exists(GoodType.class, parentGoodTypeId)) return true;

        List<GoodType> children = gf.getGoodTypesByParentId(parentGoodTypeId);
        for (GoodType gt : children)
            if (gt.getId() != id && gt.getName().equals(goodTypeName))
                return false;
        return true;
    }
}
